package org.anderground.editor.gui.properties;

import java.awt.BorderLayout;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Observable;
import java.util.Observer;

import javax.swing.BoxLayout;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;

@SuppressWarnings("serial")
public abstract class AbstractPropertiesPanel<T> extends JPanel implements
		SelectionListener, Observer {

	List<Property> properties = new LinkedList<Property>();

	private JTable table = new JTable();
	private AbstractTableModel tableModel;

	protected void updateView() {
		tableModel.fireTableDataChanged();
	}

	public void addProperty(Property c) {
		properties.add(c);
		initProperties();
	}

	public AbstractPropertiesPanel(Property... properties) {
		this.properties.addAll(Arrays.asList(properties));
		this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
		tableModel = new PropertiesTableModel();
		table.setModel(tableModel);
		initProperties();
		JScrollPane scrollPane = new JScrollPane(table);
		this.add(scrollPane, BorderLayout.CENTER);
	}

	private void initProperties() {
		for (int i = 0; i < properties.size(); i++) {
			Property property = properties.get(i);
			TableColumn column = table.getColumnModel().getColumn(i);
			column.setCellEditor(property.getCellEditor());
			column.setCellRenderer(property.getCellRender());
		}
	}

	public static interface Property {

		String getPropertyName();

		TableCellEditor getCellEditor();

		TableCellRenderer getCellRender();

		boolean isEditable();

	}

	@Override
	public void update(Observable arg0, Object arg1) {
		tableModel.fireTableDataChanged();
	}

	protected abstract int getRowCount();

	public abstract Object getValueAt(int rowIndex, int columnIndex);

	private class PropertiesTableModel extends AbstractTableModel {
		private String[] columnsNames;

		public PropertiesTableModel() {
			columnsNames = new String[properties.size()];
			for (int i = 0; i < properties.size(); i++) {
				columnsNames[i] = properties.get(i).getPropertyName();
			}
		}

		@Override
		public int getColumnCount() {
			return properties.size();
		}

		@Override
		public int getRowCount() {
			return AbstractPropertiesPanel.this.getRowCount();
		}

		@Override
		public Object getValueAt(int rowIndex, int columnIndex) {
			return AbstractPropertiesPanel.this.getValueAt(rowIndex,
					columnIndex);
		}

		public String getColumnName(int column) {
			return columnsNames[column];
		}

		public boolean isCellEditable(int row, int column) {
			try {
				return properties.get(column).isEditable();
			} catch (Exception e) {
				return false;
			}
		}
	}

}
